package com.winit.cloudlink.command;

import com.winit.cloudlink.config.Metadata;
import com.winit.cloudlink.message.Message;
import com.winit.cloudlink.message.MessageBuilder;
import com.winit.cloudlink.message.MessageEngine;

import static com.winit.cloudlink.common.utils.StringUtils.isBlank;

public abstract class CommandExecutor<C extends Command<?>> {

	private MessageEngine messageEngine;

	private Metadata metadata;

	/**
	 * 不能为空；将通过该名称调用指令
	 *
	 * @return 指令名称
	 */
	public abstract String getCommandName();

	/**
	 * 指令处理
	 *
	 * @param command
	 * @return
	 * @throws Exception
	 */
	public abstract void onReceive(C command) throws CommandException;

	@SuppressWarnings("unchecked")
	public <Payload> void callback(String toAppId, Payload payload) {
		Command<Payload> callbackCommand = new CommandBuilder<Payload>(getMetadata()).toAppId(toAppId)
				.commandName(this.getCommandName())
				.payload(payload)
				.build();

		Message<?> callbackMessage = new MessageBuilder(metadata).toApp(callbackCommand.getHeaders().getToAppId())
				.messageType(buildCallbackMessageType(toAppId))
				.payload(callbackCommand)
				.build();

		messageEngine.send(callbackMessage);
	}

	@SuppressWarnings("unchecked")
	public <Payload> void callback(String toAppId, String shardKey, Payload payload) {
		Command<Payload> callbackCommand = new CommandBuilder<Payload>(getMetadata()).toAppId(toAppId)
				.commandName(this.getCommandName(), shardKey)
				.payload(payload)
				.build();

		Message<?> callbackMessage = new MessageBuilder(metadata).toApp(callbackCommand.getHeaders().getToAppId())
				.messageType(buildCallbackMessageType(toAppId))
				.shardKey(shardKey)
				.payload(callbackCommand)
				.build();
		messageEngine.send(callbackMessage);
	}

	public MessageEngine getMessageEngine() {
		return messageEngine;
	}

	public void setMessageEngine(MessageEngine messageEngine) {
		this.messageEngine = messageEngine;
	}

	public Metadata getMetadata() {
		return metadata;
	}

	public void setMetadata(Metadata metadata) {
		this.metadata = metadata;
	}

	private String buildCallbackMessageType(String toAppId) {

		return this.getCommandName() + Constants.COMMAND_CALLBACK_SUFFIX;

	}

}
